﻿/**

 * Copyright (c) 2015-2016, FastDev 刘强 (fastdev@163.com).

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

using OF.DistributeService.Core.Attribute;
using OF.DistributeService.Core.Client;
using OF.DistributeService.Core.Common;
using OF.DistributeService.Core.Entity.Service;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TestOpenRestClient;
using TestOpenRestClient.Api;

namespace TestOpenRestClient
{
    public partial class ClientDemo : Form
    {
        public ClientDemo()
        {
            InitializeComponent();
            this.Load += ClientDemo_Load;
            this.FormClosed += ClientDemo_FormClosed;
        }

        void ClientDemo_FormClosed(object sender, FormClosedEventArgs e)
        {
            Environment.Exit(0);
            Application.Exit();
        }

        void ClientDemo_Load(object sender, EventArgs e)
        {
            this.bgWorker.DoWork += bgWorker_DoWork;
            this.bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;
            pbWorker.MarqueeAnimationSpeed = 0;
            pbWorker.Maximum = 0;
            pbWorker.Step = 3;

            Program.InitAppServices();
            //TestZKPerformance.Test();
            //new TestWf().Test();

            //ClientToAppManager.GetInstance();
        }



        private void Test2()
        {
            long a1 = 1;
            long a2 = 2;
            long a3 = a1 & a2;
        }

        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            object[] resultArray = e.Result as object[];
            object callObj = resultArray[0];
            Action<object> action = resultArray[1] as Action<object>;
            action(callObj);
        }

        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            object callResult = null;
            object[] objArray = null;
            objArray = e.Argument as object[];
            try
            {
                Func<object> func = objArray[0] as Func<object>;
                callResult = func();
            }
            catch (System.Exception ex)
            {
                callResult = ex;
            }

            e.Result = new object[] { callResult, objArray[1] };
        }

        private void btnTest1_Click(object sender, EventArgs e)
        {
            InvokeAsync(new AsyncCallContext { 
                 GetApiResult = () =>
                {
                    ClientToAppManager cm = ClientToAppManager.Get();
                    ISOService soService = cm.GetInvoker<ISOService>();
                    CallServiceResult<QuerySODTO> result = null;                    
                    int v = ++i % 4;
                    if (v == 0)
                    {
                        result = soService.AddSO(new QuerySORequest { Id = 1, Dt = new DateTime(2016, 1, 22) });
                    }
                    else if (v == 1)
                    {
                        result = soService.AddJSONSO(new QuerySORequest { Id = 1, Dt = new DateTime(2016, 1, 22) });
                    }
                    else if (v == 2)
                    {
                        result = soService.PostSO3(new QuerySORequest { Id = 1, Dt = new DateTime(2016, 1, 22) }).Result;
                    }
                    else if (v == 3)
                    {
                        result = soService.PostJSONSO3(new QuerySORequest { Id = 1, Dt = new DateTime(2016, 1, 22) }).Result;
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                    return result;
                },
                 ResultHandler = ShowCallResult
            });
        }

        public void ShowCallResult(object result)
        {
            Util.LogInfo("before set text!" + Util.GetJsonString(result));
            txtResult.Text = Util.GetJsonString(result);
            Util.LogInfo("after set text!" + txtResult.Text);
            btnTest1.Enabled = true;
            btnTest2.Enabled = true;
            pbWorker.Maximum = 0;
            pbWorker.MarqueeAnimationSpeed = 0;
        }

        public void InvokeAsync(AsyncCallContext context)
        {
            bgWorker.RunWorkerAsync(new object[] { context.GetApiResult, context.ResultHandler });
            btnTest1.Enabled = false;
            btnTest2.Enabled = false;
            pbWorker.Maximum = 10;
            pbWorker.MarqueeAnimationSpeed = 100;
        }

        public class AsyncCallContext
        {
            public Func<object> GetApiResult
            { get; set; }

            public Action<object> ResultHandler
            { get; set; }
        }
        private static int i = 0;
        private void btnTest2_Click(object sender, EventArgs e)
        {
            InvokeAsync(new AsyncCallContext
            {
                GetApiResult = () =>
                {
                    ClientToAppManager cm = ClientToAppManager.Get();
                    ISOService soService = cm.GetInvoker<ISOService>();
                    CallServiceResult<List<QuerySODTO>> result = null;
                    int v = ++i % 4;
                    if (v == 0)
                    {
                        result = soService.QuerySO(new DateTime(2016, 1, 1), 1, 2);
                    }
                    else if (v == 1)
                    {
                        result = soService.QueryJSONSO(new DateTime(2016, 1, 1), 1, 2);
                    }
                    else if (v == 2)
                    {
                        result = soService.QuerySO3(1).Result;
                    }
                    else if (v == 3)
                    {
                        result = soService.QueryJSONSO3(1).Result;
                    }
                    else {
                        throw new NotSupportedException();
                    }
                    return result;
                },
                ResultHandler = ShowCallResult
            });
        }

        private void btnPerformance_Click(object sender, EventArgs e)
        {
            InvokeAsync(new AsyncCallContext
            {
                GetApiResult = () =>
                {
                    ClientToAppManager cm = ClientToAppManager.Get();
                    DateTime dtOld = DateTime.Now;
                    ParallelOptions options = new ParallelOptions
                    {
                        MaxDegreeOfParallelism = 10
                    };
                    ISOService soService = cm.GetInvoker<ISOService>();
                    int successCallCount = 0;
                    Parallel.For(0, 1000, options, (i1) =>
                    {
                        try
                        {
                            var result = soService.PostSO3(new QuerySORequest { Id = 1 }).Result;
                            System.Threading.Interlocked.Increment(ref successCallCount);
                        }
                        catch (Exception ex)
                        {
                            Util.LogException("TestLoginPerformance", ex);
                        }
                    });
                    return new {
                        SuccessCallCount = successCallCount,
                        Elapse = DateTime.Now.Subtract(dtOld).TotalMilliseconds
                    };
                },
                ResultHandler = ShowCallResult
            });
        }
    }
}


namespace TestOpenRestClient.Api
{
    [OFDistributeService(ServiceName = "SO", Version = "1", DefaultMethod = ApiHttpMethod.Get, VirtualPath = "/SO")]
    public interface ISOService
    {
        Task<CallServiceResult<List<QuerySODTO>>> QuerySO3(int id);
        Task<CallServiceResult<List<QuerySODTO>>> QueryJSONSO3(int id);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Post, ContentFormat = ApiContentFormat.JSON)]
        Task<CallServiceResult<QuerySODTO>> PostJSONSO3(QuerySORequest request);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Post, ContentFormat = ApiContentFormat.MSGPack)]
        Task<CallServiceResult<QuerySODTO>> PostSO3(QuerySORequest request);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Post)]
        CallServiceResult<QuerySODTO> AddJSONSO(QuerySORequest request);
        CallServiceResult<List<QuerySODTO>> QueryJSONSO(DateTime? dt, int? id, int? c);

        CallServiceResult<List<QuerySODTO>> QuerySO(DateTime? dt, int? id, int? c);
        CallServiceResult<List<QuerySODTO>> QuerySO2(int id, string name);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Post)]
        CallServiceResult<QuerySODTO> AddSO(QuerySORequest request);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Delete)]
        int DeleteSO(int id, string name);
        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Put)]
        QuerySORequest UpdateSO(QuerySORequest request);
        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Delete)]
        void DeleteSO2(int id);
        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Put)]
        void UpdateSO2(QuerySORequest request);

        int GetNParams(int? a, int? b, int? c, int? d, int? e, int? f, int? g, string h, string i);

        [OFDistributeServiceMethod(HttpMethod = ApiHttpMethod.Post)]
        TestEntity TestPost(TestEntity entity);
        TestEntity TestGet(System.Boolean a, System.Byte b, System.Char c, System.DateTime d, System.Decimal e, System.Double f, System.Guid g, System.Int32 h, System.Nullable<int> i, System.String j, System.UInt32 k);
    }

    public class TestEntity
    {
        public System.Boolean a;
        public System.Byte b;
        public System.Char c;
        public System.DateTime d;
        public System.Decimal e;
        public System.Double f;
        public System.Guid g;
        public System.Int32 h;
        public System.Nullable<int> i;
        public System.String j;
        public System.UInt32 k;
        public int[] l;
        public List<int> m;
        public byte[] n;
        public TestEntity o;
        public TestEntity[] p;
        public List<TestEntity> q;
    }

    public class QuerySORequest
    {
        public int Id
        { get; set; }

        public DateTime? Dt
        { get; set; }
    }

    public class QuerySODTO
    {
        public int Id
        { get; set; }

        public decimal Amount
        { get; set; }

        public DateTime? DateTime
        { get; set; }
    }
}